package com.nulldev.util.web.flexibleKit.flexRenderer.paths;

import java.util.List;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.data.Arrays.arrays.FastLists;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.PathGenerator.PathGenerationFlags;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.BlockquoteGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.ButtonGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.EMGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.HeaderGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.ImageGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.LinebreakGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.LinkGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.ListItemGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.ParagraphGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.StrongGenerator;
import com.nulldev.util.web.flexibleKit.general.RenderOperation;
import com.nulldev.util.web.flexibleKit.general.flexDocument;
import com.nulldev.util.web.flexibleKit.jfvParse.Comment;
import com.nulldev.util.web.flexibleKit.jfvParse.Element;
import com.nulldev.util.web.flexibleKit.jfvParse.Node;
import com.nulldev.util.web.flexibleKit.jfvParse.Text;

public class RenderPathGenerator {

	private static final Logger log = LoggerFactory.getLoggerD(true);
	private static final ParagraphGenerator pg = new ParagraphGenerator();
	private static final HeaderGenerator hg = new HeaderGenerator();
	private static final ListItemGenerator li = new ListItemGenerator();
	private static final StrongGenerator strong = new StrongGenerator();
	private static final BlockquoteGenerator blockquote = new BlockquoteGenerator();
	private static final EMGenerator em = new EMGenerator();
	private static final ImageGenerator img = new ImageGenerator();
	private static final ButtonGenerator btn = new ButtonGenerator();
	private static final LinkGenerator link = new LinkGenerator();
	private static final LinebreakGenerator br = new LinebreakGenerator();

	private static final String[] BLACKLISTED_ELEMENTS = new String[]
		{ "img" };

	private static List<RenderOperation> __do_iteration(final Node n) {
		final int size = n.getChildCount();
		final int prealloc_size = size <= 10 ? 15 : size;
		final List<RenderOperation> ro = FastLists.list(prealloc_size);
		if (n.hasChildNodes()) {
			for (final Node _n : n.getChildNodes()) {
				ro.addAll(__do_iteration(_n));
			}
		} else {
			String nn = n.getNodeName();
			// log.debug("nn: " + nn);
			if (n.getParentNode() != null && !ArrayUtils.contains(BLACKLISTED_ELEMENTS, nn)) {
				nn = n.getParentNode().getNodeName();
				// log.debug("fix-nn: " + nn);
			}
			switch (nn) {
				case "font":
					log.dwarn("Treating <font> as <p>...");
					ro.add(pg.generate(n, PathGenerationFlags.RENDER_INLINE));
					break;
				case "p":
					// FIXME: <p><img></p> is treated as plain text...
					ro.add(pg.generate(n));
					break;
				case "b":
					ro.add(pg.generate(n, PathGenerationFlags.USE_BOLD_TEXT, PathGenerationFlags.RENDER_INLINE));
					break;
				case "i":
					ro.add(pg.generate(n, PathGenerationFlags.USE_ITALIC_TEXT, PathGenerationFlags.RENDER_INLINE));
					break;
				case "code":
					ro.add(pg.generate(n, PathGenerationFlags.USE_MONOSPACED_FONT, PathGenerationFlags.RENDER_INLINE));
					break;
				case "h1":
				case "h2":
				case "h3":
				case "h4":
				case "h5":
				case "h6":
					ro.add(hg.generate(n));
					break;
				case "li":
					ro.add(li.generate(n));
					break;
				case "strong":
					ro.add(strong.generate(n, PathGenerationFlags.RENDER_INLINE));
					break;
				case "blockquote":
					ro.add(blockquote.generate(n));
					break;
				case "em":
					ro.add(em.generate(n));
					break;
				case "img":
					ro.add(img.generate(n));
					break;
				case "button":
					ro.add(btn.generate(n, PathGenerationFlags.RENDER_INLINE));
					break;
				case "a":
					ro.add(link.generate(n, PathGenerationFlags.RENDER_INLINE));
					break;
				case "header":
				case "aside":
					ro.add(br.generate(n));
					break;
				case "br":
					ro.add(br.generate(n));
					break;
				case "#comment": /* Comments shouldn't be rendered. */
				case "#doctype": /* This isn't IE. */
				case "meta":
				case "title":
				case "#document":
				case "head":
				case "body":
				case "script":
					break;
				case "style": {
					log.warn("Skipped a CSS stylesheet.");
					log.warn("Z:\t" + n.getTextContent());
					break;
				}
				case "ul":
					ro.add(br.generate(n));
					break;
				case "html":
					break;
				default:
					if (n instanceof Text) {
						ro.add(pg.generate(n));
						break;
					} else {
						log.warn("Unknown render path for: " + nn);
						if (n instanceof Element) {
							JVM.println("E: \t" + ((Element) n).getOuterHTML());
						} else if (n instanceof Text) {
							JVM.println("T: \t" + ((Text) n).getData());
						} else if (n instanceof Comment) {
							JVM.println("C: \t" + ((Comment) n).getData());
						} else {
							JVM.println("Unknown inheritance for " + n + ".");
						}
					}
					break;
			}
		}
		return ro;
	}

	public static List<RenderOperation> make(final flexDocument document) {
		final List<Node> _n = document.getFVDocument().getChildNodes();
		final List<RenderOperation> ro = FastLists.list(_n.size());
		for (final Node n : _n) {
			ro.addAll(__do_iteration(n));
		}
		return ro;
	}

}
